package com.zxb.base.task;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zxb.base.task.enm.TaskStateEnum;
import com.zxb.core.common.A;
import com.zxb.core.common.C;
import com.zxb.core.common.R;
import com.zxb.core.dao.system.SysConfig;
import com.zxb.core.dao.system.SysTask;
import com.zxb.core.dao.system.SysTaskDao;
import com.zxb.base.task.service.QuartzService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.quartz.SchedulerException;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;
import java.util.List;
import java.util.Map;

/**
 * @author Zxb
 */
@Slf4j
@RestController
@AllArgsConstructor
public class TaskController {

    private QuartzService quartzService;
    private SysTaskDao taskDao;

    @GetMapping("/task/page")
    public R<?> page(String searchStr, Integer page, Integer pageSize) {
        IPage<SysTask> pageParam = new Page<>(page, pageSize);
        QueryWrapper<SysTask> queryWrapper = new QueryWrapper<>();
        if (StrUtil.isNotBlank(searchStr)) {
            queryWrapper.lambda().like(SysTask::getName, "%" + searchStr + "%");
        }
        IPage<SysTask> result = taskDao.page(pageParam, queryWrapper);
        return R.success(result);
    }

    @PostMapping("/task/changeCorn")
    public R<?> change(@RequestBody Map<String, String> map) {
        Long id = Long.valueOf(map.get("id"));
        String cron = map.get("cron");
        SysTask task = taskDao.getById(id);
        String oldCron = task.getCron();
        try {
            quartzService.modifyJob(task.getName(), cron);
            task.setCron(cron);
            taskDao.updateById(task);
        } catch (SchedulerException e) {
            e.printStackTrace();
            task.setCron(oldCron);
            taskDao.updateById(task);
            return R.error();
        }
        return R.success();
    }

    @PostMapping("/task/pause")
    public R<?> pause(@RequestBody Long id) {
        SysTask task = taskDao.getById(id);
        try {
            quartzService.pauseJob(task.getName());
            task.setState(TaskStateEnum.暂停.name());
            taskDao.updateById(task);
        } catch (SchedulerException e) {
            e.printStackTrace();
            return R.error();
        }
        return R.success();
    }

    @PostMapping("/task/resume")
    public R<?> resume(@RequestBody Long id) {
        SysTask task = taskDao.getById(id);
        try {
            quartzService.resumeJob(task.getName());
            task.setState(TaskStateEnum.运行.name());
            taskDao.updateById(task);
        } catch (SchedulerException e) {
            e.printStackTrace();
            return R.error();
        }
        return R.success();
    }

    @PostMapping("/task/del")
    public R<?> del(@RequestBody List<Long> ids) {
        for (Long id : ids) {
            SysTask task = taskDao.getById(id);
            try {
                quartzService.delJob(task.getName());
                taskDao.removeById(id);
            } catch (SchedulerException e) {
                e.printStackTrace();
            }
        }
        return R.success();
    }

    @PostMapping("/task/stop")
    public R<?> stop(@RequestBody Long id) {
        SysTask task = taskDao.getById(id);
        try {
            quartzService.delJob(task.getName());
            task.setState(TaskStateEnum.下线.name());
            taskDao.updateById(task);
        } catch (SchedulerException e) {
            e.printStackTrace();
            return R.error();
        }
        return R.success();
    }

    @PostMapping("/task/add")
    public R<?> add(@RequestBody SysTask task) {
        if (taskDao.exists(new QueryWrapper<SysTask>()
                .lambda().eq(SysTask::getName, task.getName()))) {
            return R.error("任务名称已经存在");
        }
        if (taskDao.exists(new QueryWrapper<SysTask>()
                .lambda().eq(SysTask::getCode, task.getCode()))) {
            return R.error("任务编码已经存在");
        }
        task.setState(TaskStateEnum.下线.name());
        taskDao.save(task);
        return R.success();
    }

    @PostMapping("/task/update")
    public R update(@RequestBody @Valid SysTask obj) {
        SysTask old = taskDao.getById(obj.getId());
        A.isInDatabase(old, "定时任务");
        if (taskDao.exists(
                new QueryWrapper<SysTask>()
                        .lambda()
                        .eq(SysTask::getName, obj.getName())
                        .ne(SysTask::getId, old.getId())
        )) {
            return R.error("任务名称已经存在");
        }

        if (taskDao.exists(
                new QueryWrapper<SysTask>()
                        .lambda()
                        .eq(SysTask::getCode, obj.getCode())
                        .ne(SysTask::getId, old.getId())
        )) {
            return R.error("任务编码已经存在");
        }
        BeanUtil.copyProperties(obj, old, C.IGNORED_PROPERTIES);
        taskDao.updateById(old);
        return R.success();
    }

    @PostMapping("/task/start")
    public R<?> start(@RequestBody Long id) {
        SysTask task = taskDao.getById(id);
        try {
            quartzService.addJob(task);
            task.setState(TaskStateEnum.运行.name());
            taskDao.updateById(task);
        } catch (SchedulerException e) {
            e.printStackTrace();
            task.setState(TaskStateEnum.下线.name());
            taskDao.updateById(task);
            return R.error();
        }
        return R.success();
    }

    @PostMapping("/task/go")
    public R<?> go(@RequestBody Long id) {
        SysTask task = taskDao.getById(id);
        try {
            quartzService.doJob(task);
        } catch (SchedulerException e) {
            e.printStackTrace();
            return R.error();
        }
        return R.success();
    }

    @GetMapping("/task/demo")
    public R<?> demo() {
        return R.success("测试任务");
    }
}
